#include "mqtt_file_transfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <jansson.h>
#include "connection/mqtt_client.h"

// 接收上下文
typedef struct {
    file_transfer_ctx_t *ctx;
    FILE *file;
    file_meta_t meta;
    int received_chunks;
    char *save_path;
} recv_context_t;

// 发送ACK
static int send_ack(recv_context_t *rctx, int chunk_index, int status) {
    char topic[256];
    snprintf(topic, sizeof(topic), "%s/%s", TOPIC_FILE_ACK, rctx->meta.file_id);

    // 创建JSON消息
    json_t *root = json_object();
    json_object_set_new(root, "type", json_integer(MSG_TYPE_ACK));
    json_object_set_new(root, "file_id", json_string(rctx->meta.file_id));
    json_object_set_new(root, "chunk_index", json_integer(chunk_index));
    json_object_set_new(root, "status", json_integer(status));

    char *json_msg = json_dumps(root, JSON_COMPACT);
    size_t json_len = strlen(json_msg);

    // 发送消息
    int result = neu_mqtt_client_publish(rctx->ctx->mqtt_client, 1, topic,
                                         (uint8_t *)json_msg, json_len,
                                         NULL, NULL);

    json_decref(root);
    free(json_msg);
    return result;
}

// 元数据处理
static void handle_metadata(recv_context_t *rctx,const  uint8_t *payload, uint32_t len) {
    char *msg = malloc(len + 1);
    memcpy(msg, payload, len);
    msg[len] = '\0';

    json_error_t error;
    json_t *root = json_loads(msg, 0, &error);
    free(msg);

    if (!root) {
        printf("Failed to parse metadata JSON: %s\n", error.text);
        return;
    }

    // 解析元数据
    json_t *file_id_obj = json_object_get(root, "file_id");
    json_t *filename_obj = json_object_get(root, "filename");
    json_t *file_size_obj = json_object_get(root, "file_size");
    json_t *chunk_size_obj = json_object_get(root, "chunk_size");
    json_t *total_chunks_obj = json_object_get(root, "total_chunks");

    if (!file_id_obj || !json_is_string(file_id_obj) ||
        !filename_obj || !json_is_string(filename_obj) ||
        !file_size_obj || !json_is_integer(file_size_obj) ||
        !chunk_size_obj || !json_is_integer(chunk_size_obj) ||
        !total_chunks_obj || !json_is_integer(total_chunks_obj)) {
        printf("Invalid metadata format\n");
        json_decref(root);
        return;
    }

    // 提取元数据
    strncpy(rctx->meta.file_id, json_string_value(file_id_obj), sizeof(rctx->meta.file_id));
    strncpy(rctx->meta.filename, json_string_value(filename_obj), sizeof(rctx->meta.filename));
    rctx->meta.file_size = json_integer_value(file_size_obj);
    rctx->meta.chunk_size = json_integer_value(chunk_size_obj);
    rctx->meta.total_chunks = json_integer_value(total_chunks_obj);

    json_decref(root);

    // 创建文件（保存到当前目录）
    char filepath[512];
    snprintf(filepath, sizeof(filepath), "./%s", rctx->meta.filename);

    rctx->file = fopen(filepath, "wb");
    if (!rctx->file) {
        printf("Failed to create file: %s\n", filepath);
        send_ack(rctx, -1, -1); // 发送错误ACK
        return;
    }

    printf("Receiving file: %s (size: %zu, chunks: %d)\n",
           rctx->meta.filename, rctx->meta.file_size, rctx->meta.total_chunks);

    // 发送元数据ACK
    send_ack(rctx, -1, 0);
    rctx->received_chunks = 0;
}

// 数据处理
static void handle_data(recv_context_t *rctx,const  uint8_t *payload, uint32_t len) {
    char *msg = malloc(len + 1);
    memcpy(msg, payload, len);
    msg[len] = '\0';

    json_error_t error;
    json_t *root = json_loads(msg, 0, &error);
    free(msg);

    if (!root) {
        printf("Failed to parse data JSON: %s\n", error.text);
        return;
    }

    // 解析数据
    json_t *file_id_obj = json_object_get(root, "file_id");
    json_t *chunk_index_obj = json_object_get(root, "chunk_index");
    json_t *chunk_size_obj = json_object_get(root, "chunk_size");
    json_t *data_obj = json_object_get(root, "data");

    if (!file_id_obj || !json_is_string(file_id_obj) ||
        !chunk_index_obj || !json_is_integer(chunk_index_obj) ||
        !chunk_size_obj || !json_is_integer(chunk_size_obj) ||
        !data_obj || !json_is_string(data_obj)) {
        printf("Invalid data format\n");
        json_decref(root);
        return;
    }

    // 检查文件ID是否匹配
    const char *file_id = json_string_value(file_id_obj);
    if (strcmp(file_id, rctx->meta.file_id) != 0) {
        printf("File ID mismatch: expected %s, got %s\n", rctx->meta.file_id, file_id);
        json_decref(root);
        return;
    }

    int chunk_index = json_integer_value(chunk_index_obj);
    size_t chunk_size = json_integer_value(chunk_size_obj);
    const char *encoded_data = json_string_value(data_obj);

    // Base64解码数据
    size_t decoded_size;
    uint8_t *decoded_data = base64_decode(encoded_data, strlen(encoded_data), &decoded_size);
    if (!decoded_data || decoded_size != chunk_size) {
        printf("Failed to decode data or size mismatch\n");
        json_decref(root);
        return;
    }

    // 写入文件
    fseek(rctx->file, chunk_index * rctx->meta.chunk_size, SEEK_SET);
    size_t written = fwrite(decoded_data, 1, chunk_size, rctx->file);
    free(decoded_data);
    json_decref(root);

    if (written != chunk_size) {
        printf("Failed to write chunk %d to file\n", chunk_index);
        send_ack(rctx, chunk_index, -1);
        return;
    }

    // 发送数据ACK
    send_ack(rctx, chunk_index, 0);
    rctx->received_chunks++;

    printf("Received chunk %d/%d\n", rctx->received_chunks, rctx->meta.total_chunks);

    if (rctx->ctx->progress_cb) {
        rctx->ctx->progress_cb(rctx->meta.file_id, rctx->received_chunks, rctx->meta.total_chunks);
    }

    // 检查是否完成
    if (rctx->received_chunks >= rctx->meta.total_chunks) {
        fclose(rctx->file);
        printf("File transfer completed: %s\n", rctx->meta.filename);

        if (rctx->ctx->complete_cb) {
            rctx->ctx->complete_cb(rctx->meta.file_id, 0, "Receive completed");
        }

        // 释放上下文
        free(rctx->save_path);
        free(rctx);
    }
}

// 消息回调
static void message_callback(neu_mqtt_qos_e qos,const  char *topic,
                             const uint8_t *payload, uint32_t len, void *user_data) {
    file_transfer_ctx_t *ctx = (file_transfer_ctx_t *)user_data;
    recv_context_t *rctx = (recv_context_t *)ctx->user_data;
    (void)qos;
    // 检查主题类型
    if (strstr(topic, TOPIC_FILE_META) != NULL) {
        handle_metadata(rctx, payload, len);
    } else if (strstr(topic, TOPIC_FILE_DATA) != NULL) {
        handle_data(rctx, payload, len);
    }
    return ;
}

// 订阅主题
static int subscribe_topics(file_transfer_ctx_t *ctx) {
    // 订阅元数据主题
    if (neu_mqtt_client_subscribe(ctx->mqtt_client, 1, TOPIC_FILE_META,
                                  ctx, message_callback) != 0) {
        return -1;
    }

    // 订阅数据主题
    if (neu_mqtt_client_subscribe(ctx->mqtt_client, 1, TOPIC_FILE_DATA,
                                  ctx, message_callback) != 0) {
        return -1;
    }

    return 0;
}

// 接收文件
int file_transfer_receive(file_transfer_ctx_t *ctx, const char *save_path) {
    // 创建接收上下文
    recv_context_t *rctx = malloc(sizeof(recv_context_t));
    if (!rctx) {
        return -1;
    }

    rctx->ctx = ctx;
    rctx->file = NULL;
    rctx->received_chunks = 0;
    rctx->save_path = strdup(save_path);

    // 订阅主题
    if (subscribe_topics(ctx) != 0) {
        free(rctx->save_path);
        free(rctx);
        return -1;
    }

    // 保存上下文
    ctx->user_data = rctx;

    printf("Waiting for file transfers...\n");
    return 0;
}
